﻿using SketchUpAPI.NET.Enums;
using SketchUpAPI.NET.SketchUp.Exception;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace SketchUpAPI.NET.Objects
{
    public class ComponentDefinition : Entity
    {
        #region API 函数
        /// <summary>
        /// 创建组件定义
        /// </summary>
        /// <param name="compDef"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUComponentDefinitionCreate(out IntPtr compDef);

        /// <summary>
        /// 获取组件定义的名字
        /// </summary>
        /// <param name="compDef"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUComponentDefinitionGetName(IntPtr compDef, ref IntPtr name);

        /// <summary>
        /// 设置组件的名字
        /// </summary>
        /// <remarks>注意：组件名字具有唯一性，如果该名字已经存在了，则会在该名字的基础上创建一个新的名字</remarks>
        /// <param name="compDef"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUComponentDefinitionSetName(IntPtr compDef, [MarshalAs(UnmanagedType.LPUTF8Str)] string name);

        /// <summary>
        /// 获取组件物件表
        /// </summary>
        /// <param name="compDefRef"></param>
        /// <param name="entitiesRef"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUComponentDefinitionGetEntities(IntPtr compDefRef, out IntPtr entitiesRef);

        /// <summary>
        /// 为该组件创建一个实例
        /// </summary>
        /// <param name="compDefRef"></param>
        /// <param name="instanceRef"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUComponentDefinitionCreateInstance(IntPtr compDef, out IntPtr instanceRef);

        /// <summary>
        /// 该组件使用的实例个数
        /// </summary>
        /// <param name="compDef"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUComponentDefinitionGetNumUsedInstances(IntPtr compDef, out long count);

        /// <summary>
        /// 该组件的全部实例个数，包括其他定义中使用的实例
        /// </summary>
        /// <param name="compDef"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUComponentDefinitionGetNumInstances(IntPtr compDef, out long count);

        /// <summary>
        /// 获取组件在模型中的实例
        /// </summary>
        /// <param name="compDef"></param>
        /// <param name="len"></param>
        /// <param name="instances"></param>
        /// <param name="returnCount"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUComponentDefinitionGetInstances(IntPtr compDef, long len, IntPtr[] instances, out long returnCount);
        #endregion

        /// <summary>
        /// 组件名字
        /// </summary>
        /// <remarks>注意：组件名字具有唯一性，在创建组件定义时会自动生成一个名字
        /// <para>当设置名字时，如果该名字已经存在了，则会在该名字的基础上创建一个新的名字</para></remarks>
        public string Name
        {
            get
            {
                StringRef name = StringRef.Empty;
                SketchUpExceptionHelper.ThrowSUResult(SUComponentDefinitionGetName(Id, ref name.Id));
                return name.Dispose();
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SUComponentDefinitionSetName(Id, value));
            }
        }

        /// <summary>
        /// 获取组件的物件表
        /// </summary>
        public EntityTable Entities
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUComponentDefinitionGetEntities(Id, out IntPtr id));
                return new EntityTable(id);
            }
        }

        /// <summary>
        /// 该组件的实例个数，包括其他定义中使用的实例
        /// </summary>
        public int InstanceCount
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUComponentDefinitionGetNumInstances(Id, out long count));
                return (int)count;
            }
        }

        /// <summary>
        /// 该组件添加到模型中的实例个数
        /// </summary>
        public int InstanceUsedCount
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUComponentDefinitionGetNumUsedInstances(Id, out long usedCount));
                return (int)usedCount;
            }
        }

        /// <summary>
        /// 获取组件在模型中的实例
        /// </summary>
        public List<ComponentInstance> Instances
        {
            get
            {
                IntPtr[] ptrs = new IntPtr[InstanceUsedCount];
                SketchUpExceptionHelper.ThrowSUResult(SUComponentDefinitionGetInstances(Id, InstanceUsedCount, ptrs, out long returnCount));

                return ptrs.Select(i => new ComponentInstance(i)).ToList();
            }
        }

        /// <summary>
        /// 创建一个组件定义
        /// </summary>
        public ComponentDefinition()
        {
            SketchUpExceptionHelper.ThrowSUResult(SUComponentDefinitionCreate(out Id));
        }

        /// <summary>
        /// 创建一个组件定义
        /// </summary>
        /// <param name="name">组件名字</param>
        public ComponentDefinition(string name) : this()
        {
            Name = name;
        }

        internal ComponentDefinition(IntPtr id)
        {
            this.Id = id;
        }

        /// <summary>
        /// 创建一个组件实例
        /// </summary>
        /// <returns></returns>
        public ComponentInstance CreateInstance()
        {
            SketchUpExceptionHelper.ThrowSUResult(SUComponentDefinitionCreateInstance(Id, out IntPtr id));
            return new ComponentInstance(id);
        }
    }
}
